var Card = new function () 
{
	var width = 80;
	var height = 120;
  var num_w = 3;
  var num_h = 2;
	var padding = 2;
	var fgColor = "#CCCCCC";
	var bgColor = "#000000";
  var slColor = "#FFFFFF";
	var font = "12px sans serif";
  var data = [];
  var board = [];
  var ctx = 0;
  var selected = -1;
  var offset = {x:0, y:0};
  var animating = false;
  var images = [];
  
  this.Images = [];
	this.Width = 70;
	this.Height = 100;
	this.Padding = 2;

  // set current card states
  this.setData = function(d)
	{
		data = d;
	}
  this.getCost = function(cardData)
  {
    return cardData.health+cardData.attack;
  }
  this.newDrawCard = function(canvas, card, selected)
  {
    var ctx = canvas.getContext("2d");
    var hw = this.Width/2;
    var hh = this.Height/2;
    
    hw = hw+this.Padding;
    hh = hh+this.Padding;
    if (selected)
    {
      ctx.fillStyle = slColor;
    }
    else
    {
      ctx.fillStyle = bgColor;
    }
    ctx.fillRect(card.p.x-hw, card.p.y-hh, hw*2, hh*2);
    
    ctx.fillStyle = fgColor;
    
    hw = hw-this.Padding;
    hh = hh-this.Padding;
    if (this.Images[card.imgIndex])
    {
      ctx.drawImage(this.Images[card.imgIndex], card.p.x-hw, card.p.y-hh);
    }
    else
    {
      ctx.fillRect(card.p.x-hw, card.p.y-hh, hw*2, hw*2);
    }
    
    
    
    var radius = this.Padding*4;
    
    ctx.fillStyle = "#005500";
    ctx.beginPath();
    ctx.arc(card.p.x-(hw-radius), card.p.y-(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    ctx.fillStyle = "#550000";
    ctx.beginPath();
    ctx.arc(card.p.x+(hw-radius), card.p.y-(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    ctx.fillStyle = "#555555";
    ctx.beginPath();
    ctx.arc(card.p.x-(hw-radius), card.p.y+(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    ctx.fillStyle = "#555500";
    ctx.beginPath();
    ctx.arc(card.p.x+(hw-radius), card.p.y+(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    hw = hw-this.Padding*4;
    hh = hh-this.Padding*4;
    
    ctx.fillStyle = "#FFFFFF";
    ctx.font = font;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle"; 
    
    ctx.fillText(card.health.toString(),            card.p.x-hw, card.p.y-hh);
    ctx.fillText(card.attack.toString(),            card.p.x+hw, card.p.y-hh);
    ctx.fillText(card.type.toString(),              card.p.x-hw, card.p.y+hh);
    ctx.fillText(this.getCost(card).toString(),     card.p.x+hw, card.p.y+hh);
    
    
    if (selected)
    {
      ctx.fillStyle = "#000000";
    }
    ctx.textBaseline = "top";
    var textHeight = (this.Height/2)-(this.Height-this.Width);
    ctx.fillText(card.name, card.p.x, card.p.y+textHeight);
  
  }
  // draw card
  this.drawCard = function(card, light)
  {
    var hw = width/2;
    var hh = height/2;
    
    
    hw = hw+padding;
    hh = hh+padding;
    if (light)
    {
      ctx.fillStyle = slColor;
    }
    else
    {
      ctx.fillStyle = bgColor;
    }
    ctx.fillRect(card.p.x-hw, card.p.y-hh, hw*2, hh*2);
    
    ctx.fillStyle = fgColor;
    
    hw = hw-padding;
    hh = hh-padding;
    if (card.i != -1)
    {
      ctx.drawImage(images[card.i], card.p.x-hw, card.p.y-hh);
    }
    else
    {
      ctx.fillRect(card.p.x-hw, card.p.y-hh, hw*2, hh*2);
    }
    
    
    ctx.fillStyle = slColor;
    
    var radius = padding*4;
    ctx.beginPath();
    ctx.arc(card.p.x-(hw-radius), card.p.y-(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    ctx.beginPath();
    ctx.arc(card.p.x+(hw-radius), card.p.y-(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    ctx.beginPath();
    ctx.arc(card.p.x-(hw-radius), card.p.y+(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    ctx.beginPath();
    ctx.arc(card.p.x+(hw-radius), card.p.y+(hh-radius), radius, 0, 2 * Math.PI, false);
    ctx.closePath();
    ctx.fill();
    
    hw = hw-padding*4;
    hh = hh-padding*4;
    
    ctx.font = font;
    ctx.fillStyle = fgColor;
    ctx.textAlign = "center";
    ctx.textBaseline = "middle"; 
    ctx.fillText(card.n, card.p.x, card.p.y);
    
    ctx.fillText(card.type.toString(),    card.p.x-hw, card.p.y-hh);
    ctx.fillText(card.cost.toString(),    card.p.x+hw, card.p.y-hh);
    ctx.fillText(card.attack.toString(),  card.p.x-hw, card.p.y+hh);
    ctx.fillText(card.health.toString(),  card.p.x+hw, card.p.y+hh);
  }
	this.draw = function()
	{
    ctx.fillStyle = "#111111";
    ctx.fillRect(0, 0, cvs.width, cvs.height);
    
    var pw = (width+padding*2)/2;
    var ph = (height+padding*2)/2;
    
    ctx.fillStyle = "#555555";
    for (var i = 0; i < board.length; i++) 
    {
      ctx.fillRect(board[i].p.x-pw, board[i].p.y-ph, pw*2, ph*2);
    }
    
    for (var i = 0; i < data.length; i++) 
    {
      if (selected == i)
        this.drawCard(data[i], true);
      else
        this.drawCard(data[i], false);
    }
	}
  this.init = function(canvas, w, h, nw, nh, p, imgs)
  {
    width=w;
    height=h;
    num_w = nw;
    num_h = nh;
    padding = p;
		ctx = canvas.getContext("2d");
    cvs = canvas;
    images = imgs;
  }
  this.addCard = function()
  {
    var board_pile = board.length-1;
    data[data.length] = 
      {
        p:{x:board[board_pile].p.x,y:board[board_pile].p.y}, 
        b:(Math.floor(Math.random() * board_pile)),
        i:(Math.ceil(Math.random()*0.999 * images.length)-1),
        cost:Math.floor((Math.random() * 10) + 1),
        attack:Math.floor((Math.random() * 10) + 1),
        health:Math.floor((Math.random() * 10) + 1),
        type:Math.floor((Math.random() * 10) + 1),
        n:"A"
      };
  }
  this.resizeCanvas = function()
  {
    var hw = width/2;
    var hh = height/2;
    var w = 0;
    var h = 0;
    for (var i=0; i<board.length; i++)
    {
      w = Math.max(w, board[i].p.x+hw);
      h = Math.max(h, board[i].p.y+hh);
    }
    cvs.width = w;
    cvs.height = h;
  }
  this.generate = function()
  {
    var pw = width+padding*3;
    var ph = height+padding*3;
    board = [];
    for (var x = 0; x < num_w; x++) {
      for (var y = 0; y < num_h; y++) {
        board[x*num_h+y] = { 
          p:{x:((x+0.5)*pw),y:((y+0.5)*ph)}
        };
      }
    }
    
    var board_pile = board.length;
    board[board_pile] = { 
          p:{x:((num_w+0.5)*pw),y:0.5*ph}
        };
    data = [];
    for (var k = 0; k<num_w; k++)
    {
      this.addCard();
    }
    this.resizeCanvas();
    this.animate();
    this.draw();
  }
  this.findCard = function(p)
  {
    var hw = width/2;
    var hh = height/2;
    for (var i = data.length-1; i >=0; i--) {
      if (data[i].p.x-hw < p.x && data[i].p.y-hh < p.y && (data[i].p.x+hw) > p.x && (data[i].p.y + hh) > p.y) 
      {
        return i;
      }
    }
    return -1;
  }
  this.moveCardLast = function(index)
  {
    var card = data[index];
    for (var i = index; i < data.length-1; i++) {
      data[i] = data[i+1];
    }
    data[data.length-1] = card;
    return data.length-1;
  }
  this.findClosestBoard = function(p)
  {
    var boardIndex = -1;
    var minLen = 100000;
    
    for (var i = 0; i < board.length; i++) {
      var len = (p.x-board[i].p.x)*(p.x-board[i].p.x) + (p.y-board[i].p.y)*(p.y-board[i].p.y);
      if (len < minLen) {
        boardIndex = i;
        minLen = len;
      }
    }
    if (minLen < width*height)
    {
      return boardIndex;
    }
    return -1;
  }
  
  this.animate = function()
  {
    if (animating)
    {
      return 0;
    } 
    animating = true;
    var timeHandle = setInterval(function()
    {
      var running = false;
      for (var i = 0; i <data.length; i++) 
      {
        if (i==selected)
        {
          continue;
        }
        var p = board[data[i].b].p;
        var x = p.x-data[i].p.x;
        var y = p.y-data[i].p.y;
        if (x*x+y*y < 1)
        {
           data[i].p.x = p.x;
           data[i].p.y = p.y;
        }
        else
        {
          running = true;
          data[i].p.x = data[i].p.x+(x*0.1);
          data[i].p.y = data[i].p.y+(y*0.1);
        }
      }
      Card.draw();
      if (!running)
      {
        clearInterval(timeHandle);
        animating = false;
      }
    }, 20);
    return 1;
  }
  this.findCardOnBoard = function(boardIndex)
  {
      for (var i=0; i<data.length; i++)
      {
        if (data[i].b == boardIndex)
        {
          return i;
        }
      }
      return -1;
  }
  this.deselect = function()
  {
    if (selected != -1)
    {
      var boardIndex = this.findClosestBoard(data[selected].p);
      var cardInBoard = this.findCardOnBoard(boardIndex);
      if (cardInBoard == -1)
      {
        data[selected].b = boardIndex;
      }
      selected = -1;
      this.draw();
      this.animate();
    }
  }
  this.save = function(index, card)
  {
    localStorage.setItem("card"+index, JSON.stringify(card));
  }
  this.load = function(index)
  {
    var value = localStorage.getItem("card"+index);
    if (value)
    {
      return JSON.parse(value);
    }
    return 0;
  }
  this.move = function(p)
  {
    if (selected == -1)
    {
      var index = this.findCard(p);
      if (index != -1)
      {
        selected = this.moveCardLast(index);
        if (selected != -1)
        {
          offset.x = data[selected].p.x - p.x;
          offset.y = data[selected].p.y - p.y;
        }
      }
    }
    else
    { 
      data[selected].p = { 
        x: (p.x+offset.x), 
        y: (p.y+offset.y)
      };
    }
    this.draw();
  }
  function getElemOffset( element )
  {
    var offsetX = 0, offsetY = 0;
    // Compute the total offset
    if (element.offsetParent !== undefined) {
      do {
        offsetX += element.offsetLeft;
        offsetY += element.offsetTop;
      } while ((element = element.offsetParent));
    }
    return { x: offsetX, y: offsetY };
  }
	this.addInputListeners = function()
  {
    var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0));
    if (!isTouch)
    {
      var mouseStart = function(event) 
      {
        if (event.which == 1)
        {
          var offset = getElemOffset(cvs);
          var p = { 
            x : event.pageX - offset.x,
            y : event.pageY - offset.y
          };
          Card.move(p);
        }
        else
        {
          Card.deselect();
        }
      }
      cvs.addEventListener('mousedown', mouseStart);
      cvs.addEventListener('mousemove', mouseStart);
      cvs.addEventListener('mouseup', function(event) 
      {
        Card.deselect();
      });
    }
    else
    {
      var touchStart = function (event) 
      {
        if (event.targetTouches.length == 1) 
        {
          var offset = getElemOffset(cvs);
          var p = { 
            x : event.targetTouches[0].pageX - offset.x,
            y : event.targetTouches[0].pageY - offset.y
          };
          Card.move(p);
          if (selected != -1)
          {
            event.preventDefault();
          }
        }
        else
        {
          Card.deselect();
        }
      }
      cvs.addEventListener('touchstart', touchStart);
      cvs.addEventListener('touchmove', touchStart);
      cvs.addEventListener('touchend', function () 
      {
        Card.deselect();
      });
    }
  }
}

